{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\ProgramData\\Anaconda3\\lib\\site-packages\\lightfm\\_lightfm_fast.py:9: UserWarning: LightFM was compiled without OpenMP support. Only a single thread will be used.\n",
      "  warnings.warn('LightFM was compiled without OpenMP support. '\n",
      "b'Skipping line 6452: expected 8 fields, saw 9\\nSkipping line 43667: expected 8 fields, saw 10\\nSkipping line 51751: expected 8 fields, saw 9\\n'\n",
      "b'Skipping line 92038: expected 8 fields, saw 9\\nSkipping line 104319: expected 8 fields, saw 9\\nSkipping line 121768: expected 8 fields, saw 9\\n'\n",
      "b'Skipping line 144058: expected 8 fields, saw 9\\nSkipping line 150789: expected 8 fields, saw 9\\nSkipping line 157128: expected 8 fields, saw 9\\nSkipping line 180189: expected 8 fields, saw 9\\nSkipping line 185738: expected 8 fields, saw 9\\n'\n",
      "b'Skipping line 209388: expected 8 fields, saw 9\\nSkipping line 220626: expected 8 fields, saw 9\\nSkipping line 227933: expected 8 fields, saw 11\\nSkipping line 228957: expected 8 fields, saw 10\\nSkipping line 245933: expected 8 fields, saw 9\\nSkipping line 251296: expected 8 fields, saw 9\\nSkipping line 259941: expected 8 fields, saw 9\\nSkipping line 261529: expected 8 fields, saw 9\\n'\n",
      "C:\\ProgramData\\Anaconda3\\lib\\site-packages\\IPython\\core\\interactiveshell.py:2785: DtypeWarning: Columns (3) have mixed types. Specify dtype option on import or set low_memory=False.\n",
      "  interactivity=interactivity, compiler=compiler, result=result)\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from datetime import datetime, timedelta\n",
    "from sklearn import preprocessing\n",
    "from lightfm import LightFM\n",
    "from scipy.sparse import csr_matrix \n",
    "from scipy.sparse import coo_matrix \n",
    "from sklearn.metrics import roc_auc_score\n",
    "import time\n",
    "from lightfm.evaluation import auc_score\n",
    "import pickle\n",
    "import re\n",
    "import seaborn as sns\n",
    "\n",
    "\n",
    "books = pd.read_csv('BX-Books.csv', sep=';', error_bad_lines=False, encoding=\"latin-1\")\n",
    "books.columns = ['ISBN', 'bookTitle', 'bookAuthor', 'yearOfPublication', 'publisher', 'imageUrlS', 'imageUrlM', 'imageUrlL']\n",
    "users = pd.read_csv('BX-Users.csv', sep=';', error_bad_lines=False, encoding=\"latin-1\")\n",
    "users.columns = ['userID', 'Location', 'Age']\n",
    "ratings = pd.read_csv('BX-Book-Ratings.csv', sep=';', error_bad_lines=False, encoding=\"latin-1\")\n",
    "ratings.columns = ['userID', 'ISBN', 'bookRating']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1149780, 3)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ratings.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>userID</th>\n",
       "      <th>ISBN</th>\n",
       "      <th>bookRating</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>276725</td>\n",
       "      <td>034545104X</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>276726</td>\n",
       "      <td>0155061224</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>276727</td>\n",
       "      <td>0446520802</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>276729</td>\n",
       "      <td>052165615X</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>276729</td>\n",
       "      <td>0521795028</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   userID        ISBN  bookRating\n",
       "0  276725  034545104X           0\n",
       "1  276726  0155061224           5\n",
       "2  276727  0446520802           0\n",
       "3  276729  052165615X           3\n",
       "4  276729  0521795028           6"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ratings.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "books.drop(['imageUrlS', 'imageUrlM', 'imageUrlL'],axis=1,inplace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "books.loc[books.ISBN == '0789466953','yearOfPublication'] = 2000\n",
    "books.loc[books.ISBN == '0789466953','bookAuthor'] = \"James Buckley\"\n",
    "books.loc[books.ISBN == '0789466953','publisher'] = \"DK Publishing Inc\"\n",
    "books.loc[books.ISBN == '0789466953','bookTitle'] = \"DK Readers: Creating the X-Men, How Comic Books Come to Life (Level 4: Proficient Readers)\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "books.loc[books.ISBN == '078946697X','yearOfPublication'] = 2000\n",
    "books.loc[books.ISBN == '078946697X','bookAuthor'] = \"Michael Teitelbaum\"\n",
    "books.loc[books.ISBN == '078946697X','publisher'] = \"DK Publishing Inc\"\n",
    "books.loc[books.ISBN == '078946697X','bookTitle'] = \"DK Readers: Creating the X-Men, How It All Began (Level 4: Proficient Readers)\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>ISBN</th>\n",
       "      <th>bookTitle</th>\n",
       "      <th>bookAuthor</th>\n",
       "      <th>yearOfPublication</th>\n",
       "      <th>publisher</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>209538</th>\n",
       "      <td>078946697X</td>\n",
       "      <td>DK Readers: Creating the X-Men, How It All Beg...</td>\n",
       "      <td>Michael Teitelbaum</td>\n",
       "      <td>2000</td>\n",
       "      <td>DK Publishing Inc</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>221678</th>\n",
       "      <td>0789466953</td>\n",
       "      <td>DK Readers: Creating the X-Men, How Comic Book...</td>\n",
       "      <td>James Buckley</td>\n",
       "      <td>2000</td>\n",
       "      <td>DK Publishing Inc</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              ISBN                                          bookTitle  \\\n",
       "209538  078946697X  DK Readers: Creating the X-Men, How It All Beg...   \n",
       "221678  0789466953  DK Readers: Creating the X-Men, How Comic Book...   \n",
       "\n",
       "                bookAuthor yearOfPublication          publisher  \n",
       "209538  Michael Teitelbaum              2000  DK Publishing Inc  \n",
       "221678       James Buckley              2000  DK Publishing Inc  "
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "books.loc[(books.ISBN == '0789466953') | (books.ISBN == '078946697X'),:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "books.loc[books.ISBN == '2070426769','yearOfPublication'] = 2003\n",
    "books.loc[books.ISBN == '2070426769','bookAuthor'] = \"Jean-Marie Gustave Le ClÃ?Â©zio\"\n",
    "books.loc[books.ISBN == '2070426769','publisher'] = \"Gallimard\"\n",
    "books.loc[books.ISBN == '2070426769','bookTitle'] = \"Peuple du ciel, suivi de 'Les Bergers\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "books.yearOfPublication=pd.to_numeric(books.yearOfPublication, errors='coerce')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "books.loc[(books.yearOfPublication > 2006) | (books.yearOfPublication == 0),'yearOfPublication'] = np.NAN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "books.yearOfPublication.fillna(round(books.yearOfPublication.mean()), inplace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "books.yearOfPublication.isnull().sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "books.loc[(books.ISBN == '193169656X'),'publisher'] = 'other'\n",
    "books.loc[(books.ISBN == '1931696993'),'publisher'] = 'other'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "users.loc[(users.Age > 90) | (users.Age < 5), 'Age'] = np.nan"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "users.Age = users.Age.fillna(users.Age.mean())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "users.Age = users.Age.astype(np.int32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [],
   "source": [
    "ratings_new = ratings[ratings.ISBN.isin(books.ISBN)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [],
   "source": [
    "ratings = ratings[ratings.userID.isin(users.userID)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "metadata": {},
   "outputs": [],
   "source": [
    "ratings_explicit = ratings_new[ratings_new.bookRating != 0]\n",
    "ratings_implicit = ratings_new[ratings_new.bookRating == 0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "sns.countplot(data=ratings_explicit , x='bookRating')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(189988, 3)"
      ]
     },
     "execution_count": 128,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "counts1 = ratings_explicit['userID'].value_counts()\n",
    "ratings_explicit = ratings_explicit[ratings_explicit['userID'].isin(counts1[counts1 >= 30].index)]\n",
    "counts = ratings_explicit['bookRating'].value_counts()\n",
    "ratings_explicit = ratings_explicit[ratings_explicit['bookRating'].isin(counts[counts >= 30].index)]\n",
    "ratings_explicit.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 129,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(2140, 99526)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th>ISBN</th>\n",
       "      <th>0000913154</th>\n",
       "      <th>0001046438</th>\n",
       "      <th>000104687X</th>\n",
       "      <th>0001047213</th>\n",
       "      <th>0001047973</th>\n",
       "      <th>000104799X</th>\n",
       "      <th>0001048082</th>\n",
       "      <th>0001053736</th>\n",
       "      <th>0001053744</th>\n",
       "      <th>0001055607</th>\n",
       "      <th>...</th>\n",
       "      <th>B0000T6KIM</th>\n",
       "      <th>B0000VZEH8</th>\n",
       "      <th>B0000VZEJQ</th>\n",
       "      <th>B0000X8HIE</th>\n",
       "      <th>B00011SOXI</th>\n",
       "      <th>B00013AX9E</th>\n",
       "      <th>B0001FZGRQ</th>\n",
       "      <th>B0001GMSV2</th>\n",
       "      <th>B0001I1KOG</th>\n",
       "      <th>B000234N3A</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>userID</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>254</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>507</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>638</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>643</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>882</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 99526 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "ISBN    0000913154  0001046438  000104687X  0001047213  0001047973  \\\n",
       "userID                                                               \n",
       "254              0           0           0           0           0   \n",
       "507              0           0           0           0           0   \n",
       "638              0           0           0           0           0   \n",
       "643              0           0           0           0           0   \n",
       "882              0           0           0           0           0   \n",
       "\n",
       "ISBN    000104799X  0001048082  0001053736  0001053744  0001055607  \\\n",
       "userID                                                               \n",
       "254              0           0           0           0           0   \n",
       "507              0           0           0           0           0   \n",
       "638              0           0           0           0           0   \n",
       "643              0           0           0           0           0   \n",
       "882              0           0           0           0           0   \n",
       "\n",
       "ISBN       ...      B0000T6KIM  B0000VZEH8  B0000VZEJQ  B0000X8HIE  \\\n",
       "userID     ...                                                       \n",
       "254        ...               0           0           0           0   \n",
       "507        ...               0           0           0           0   \n",
       "638        ...               0           0           0           0   \n",
       "643        ...               0           0           0           0   \n",
       "882        ...               0           0           0           0   \n",
       "\n",
       "ISBN    B00011SOXI  B00013AX9E  B0001FZGRQ  B0001GMSV2  B0001I1KOG  B000234N3A  \n",
       "userID                                                                          \n",
       "254              0           0           0           0           0           0  \n",
       "507              0           0           0           0           0           0  \n",
       "638              0           0           0           0           0           0  \n",
       "643              0           0           0           0           0           0  \n",
       "882              0           0           0           0           0           0  \n",
       "\n",
       "[5 rows x 99526 columns]"
      ]
     },
     "execution_count": 129,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Generating ratings matrix from explicit ratings table\n",
    "ratings_matrix = ratings_explicit.pivot(index='userID', columns='ISBN', values='bookRating')\n",
    "userID = ratings_matrix.index\n",
    "ISBN = ratings_matrix.columns\n",
    "ratings_matrix.fillna(0, inplace = True)\n",
    "ratings_matrix = ratings_matrix.astype(np.int32)\n",
    "print(ratings_matrix.shape)\n",
    "ratings_matrix.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "metadata": {},
   "outputs": [],
   "source": [
    "user_ids = list(ratings_matrix.index)\n",
    "user_dict = {}\n",
    "counter = 0 \n",
    "for i in user_ids:\n",
    "    user_dict[i] = counter\n",
    "    counter += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "metadata": {},
   "outputs": [],
   "source": [
    "item_dict ={}\n",
    "for i in range(books.shape[0]):\n",
    "    item_dict[(books.loc[i,'ISBN'])] = books.loc[i,'bookAuthor']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "metadata": {},
   "outputs": [],
   "source": [
    "def create_implicit_feedback_matrix1(df, split_ratio):\n",
    "    # assume df.columns=['visitorid','itemid','event']\n",
    "    split_point = np.int(np.round(df.shape[0] * split_ratio))\n",
    "    df_train = df.iloc[0:split_point]\n",
    "    df_test = df.iloc[split_point::]\n",
    "    df_test = df_test[(df_test['userID'].isin(df_train['userID'])) & \\\n",
    "                      (df_test['ISBN'].isin(df_train['ISBN']))]\n",
    "    id_cols = ['userID', 'ISBN']\n",
    "    trans_cat_train = dict()\n",
    "    trans_cat_test = dict()\n",
    "    for k in id_cols:\n",
    "        cate_enc = preprocessing.LabelEncoder()\n",
    "        trans_cat_train[k] = cate_enc.fit_transform(df_train[k].values)\n",
    "        trans_cat_test[k] = cate_enc.transform(df_test[k].values)\n",
    "\n",
    "    # --- Encode ratings:\n",
    "    cate_enc = preprocessing.LabelEncoder()\n",
    "    ratings = dict()\n",
    "    ratings['train'] = cate_enc.fit_transform(df_train.bookRating)\n",
    "    ratings['test'] = cate_enc.transform(df_test.bookRating)\n",
    "\n",
    "    n_users = len(np.unique(trans_cat_train['userID']))\n",
    "    n_items = len(np.unique(trans_cat_train['ISBN']))\n",
    "\n",
    "\n",
    "    rate_matrix['train'] = coo_matrix((ratings['train'], (trans_cat_train['userID'], \\\n",
    "                                                          trans_cat_train['ISBN'])) \\\n",
    "                                      , shape=(n_users, n_items))\n",
    "    rate_matrix['test'] = coo_matrix((ratings['test'], (trans_cat_test['userID'], \\\n",
    "                                                        trans_cat_test['ISBN'])) \\\n",
    "                                     , shape=(n_users, n_items))\n",
    "    return rate_matrix"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "metadata": {},
   "outputs": [],
   "source": [
    "import scipy.sparse as sp\n",
    "\n",
    "def _shuffle(uids, iids, data, random_state):\n",
    "\n",
    "    shuffle_indices = np.arange(len(uids))\n",
    "    random_state.shuffle(shuffle_indices)\n",
    "\n",
    "    return (uids[shuffle_indices],\n",
    "            iids[shuffle_indices],\n",
    "            data[shuffle_indices])\n",
    "\n",
    "def random_train_test_split(interactions_df,\n",
    "                            test_percentage=0.25,\n",
    "                            random_state=None):\n",
    "    \"\"\"\n",
    "    Randomly split interactions between training and testing.\n",
    "\n",
    "    This function takes an interaction set and splits it into\n",
    "    two disjoint sets, a training set and a test set. Note that\n",
    "    no effort is made to make sure that all items and users with\n",
    "    interactions in the test set also have interactions in the\n",
    "    training set; this may lead to a partial cold-start problem\n",
    "    in the test set.\n",
    "\n",
    "    Parameters\n",
    "    ----------\n",
    "\n",
    "    interactions: a scipy sparse matrix containing interactions\n",
    "        The interactions to split.\n",
    "    test_percentage: float, optional\n",
    "        The fraction of interactions to place in the test set.\n",
    "    random_state: np.random.RandomState, optional\n",
    "        The random state used for the shuffle.\n",
    "\n",
    "    Returns\n",
    "    -------\n",
    "\n",
    "    (train, test): (scipy.sparse.COOMatrix,\n",
    "                    scipy.sparse.COOMatrix)\n",
    "         A tuple of (train data, test data)\n",
    "    \"\"\"\n",
    "    interactions = csr_matrix(interactions_df.values)\n",
    "    if random_state is None:\n",
    "        random_state = np.random.RandomState()\n",
    "\n",
    "    interactions = interactions.tocoo()\n",
    "\n",
    "    shape = interactions.shape\n",
    "    uids, iids, data = (interactions.row,\n",
    "                        interactions.col,\n",
    "                        interactions.data)\n",
    "\n",
    "    uids, iids, data = _shuffle(uids, iids, data, random_state)\n",
    "\n",
    "    cutoff = int((1.0 - test_percentage) * len(uids))\n",
    "\n",
    "    train_idx = slice(None, cutoff)\n",
    "    test_idx = slice(cutoff, None)\n",
    "\n",
    "    train = coo_matrix((data[train_idx],\n",
    "                           (uids[train_idx],\n",
    "                            iids[train_idx])),\n",
    "                          shape=shape,\n",
    "                          dtype=interactions.dtype)\n",
    "    test = coo_matrix((data[test_idx],\n",
    "                          (uids[test_idx],\n",
    "                           iids[test_idx])),\n",
    "                         shape=shape,\n",
    "                         dtype=interactions.dtype)\n",
    "\n",
    "    return train, test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "metadata": {},
   "outputs": [],
   "source": [
    "train, test = random_train_test_split(ratings_matrix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- Run time:  4.857818941275279 mins ---\n",
      "\n",
      "Train AUC 0.991\n",
      "\n",
      "Test AUC 0.634\n",
      "\n"
     ]
    }
   ],
   "source": [
    "start_time = time.time()\n",
    "model=LightFM(no_components=115,learning_rate=0.027,loss='warp')\n",
    "model.fit(train,epochs=12,num_threads=4)\n",
    "with open('saved_model','wb') as f:\n",
    "    saved_model={'model':model}\n",
    "    pickle.dump(saved_model, f)\n",
    "auc_train = auc_score(model, train).mean()\n",
    "auc_test = auc_score(model, test).mean()\n",
    "\n",
    "#df=df.assign(pred_score=model.predict(df['visitorid'],df['itemid']))\n",
    "\n",
    "#df_auc=df.groupby(by='visitorid').apply(lambda df: roc_auc_score(df['event'].values,df['pred_score'].values))\n",
    "#print('Training auc %0.3f' % numpy.mean([i for i in df_auc.values if i > -1]))\n",
    "\n",
    "print(\"--- Run time:  %s mins ---\\n\" % ((time.time() - start_time)/60))\n",
    "print(\"Train AUC %.3f\\n\"%auc_train)\n",
    "print(\"Test AUC %.3f\\n\"%auc_test)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "metadata": {},
   "outputs": [],
   "source": [
    "from skopt import forest_minimize\n",
    "\n",
    "def objective(params):\n",
    "    # unpack\n",
    "    epochs, learning_rate, no_components = params\n",
    "\n",
    "    model = LightFM(loss='warp',\n",
    "                    random_state=2016,\n",
    "                    learning_rate=learning_rate,\n",
    "                    no_components=no_components)\n",
    "    model.fit(train, epochs=epochs,\n",
    "              num_threads=4, verbose=True)\n",
    "    \n",
    "    patks = auc_score(model, test,num_threads=4)\n",
    "    maptk = np.mean(patks)\n",
    "    # Make negative because we want to _minimize_ objective\n",
    "    out = -maptk\n",
    "    # Handle some weird numerical shit going on\n",
    "    if np.abs(out + 1) < 0.01 or out < -1.0:\n",
    "        return 0.0\n",
    "    else:\n",
    "        return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 117,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration No: 1 started. Evaluating function at random point.\n",
      "Epoch 0\n",
      "Iteration No: 1 ended. Evaluation done at random point.\n",
      "Time taken: 48.0505\n",
      "Function value obtained: -0.5512\n",
      "Current minimum: -0.5512\n",
      "Iteration No: 2 started. Evaluating function at random point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Iteration No: 2 ended. Evaluation done at random point.\n",
      "Time taken: 43.6741\n",
      "Function value obtained: -0.6075\n",
      "Current minimum: -0.6075\n",
      "Iteration No: 3 started. Evaluating function at random point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Epoch 10\n",
      "Epoch 11\n",
      "Epoch 12\n",
      "Epoch 13\n",
      "Epoch 14\n",
      "Epoch 15\n",
      "Epoch 16\n",
      "Epoch 17\n",
      "Epoch 18\n",
      "Epoch 19\n",
      "Epoch 20\n",
      "Epoch 21\n",
      "Epoch 22\n",
      "Epoch 23\n",
      "Iteration No: 3 ended. Evaluation done at random point.\n",
      "Time taken: 97.6259\n",
      "Function value obtained: -0.5141\n",
      "Current minimum: -0.6075\n",
      "Iteration No: 4 started. Evaluating function at random point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Epoch 10\n",
      "Epoch 11\n",
      "Epoch 12\n",
      "Iteration No: 4 ended. Evaluation done at random point.\n",
      "Time taken: 53.8290\n",
      "Function value obtained: -0.5183\n",
      "Current minimum: -0.6075\n",
      "Iteration No: 5 started. Evaluating function at random point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Epoch 10\n",
      "Epoch 11\n",
      "Epoch 12\n",
      "Epoch 13\n",
      "Epoch 14\n",
      "Epoch 15\n",
      "Epoch 16\n",
      "Epoch 17\n",
      "Epoch 18\n",
      "Epoch 19\n",
      "Epoch 20\n",
      "Epoch 21\n",
      "Epoch 22\n",
      "Epoch 23\n",
      "Iteration No: 5 ended. Evaluation done at random point.\n",
      "Time taken: 111.9715\n",
      "Function value obtained: -0.6012\n",
      "Current minimum: -0.6075\n",
      "Iteration No: 6 started. Evaluating function at random point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Epoch 10\n",
      "Epoch 11\n",
      "Epoch 12\n",
      "Epoch 13\n",
      "Epoch 14\n",
      "Epoch 15\n",
      "Epoch 16\n",
      "Epoch 17\n",
      "Epoch 18\n",
      "Epoch 19\n",
      "Epoch 20\n",
      "Epoch 21\n",
      "Epoch 22\n",
      "Epoch 23\n",
      "Epoch 24\n",
      "Epoch 25\n",
      "Epoch 26\n",
      "Epoch 27\n",
      "Epoch 28\n",
      "Epoch 29\n",
      "Epoch 30\n",
      "Epoch 31\n",
      "Epoch 32\n",
      "Epoch 33\n",
      "Epoch 34\n",
      "Epoch 35\n",
      "Epoch 36\n",
      "Epoch 37\n",
      "Iteration No: 6 ended. Evaluation done at random point.\n",
      "Time taken: 61.9337\n",
      "Function value obtained: -0.5737\n",
      "Current minimum: -0.6075\n",
      "Iteration No: 7 started. Evaluating function at random point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Iteration No: 7 ended. Evaluation done at random point.\n",
      "Time taken: 64.9591\n",
      "Function value obtained: -0.6203\n",
      "Current minimum: -0.6203\n",
      "Iteration No: 8 started. Evaluating function at random point.\n",
      "Epoch 0\n",
      "Iteration No: 8 ended. Evaluation done at random point.\n",
      "Time taken: 70.4652\n",
      "Function value obtained: -0.5034\n",
      "Current minimum: -0.6203\n",
      "Iteration No: 9 started. Evaluating function at random point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Epoch 10\n",
      "Epoch 11\n",
      "Epoch 12\n",
      "Epoch 13\n",
      "Epoch 14\n",
      "Epoch 15\n",
      "Epoch 16\n",
      "Epoch 17\n",
      "Epoch 18\n",
      "Epoch 19\n",
      "Epoch 20\n",
      "Epoch 21\n",
      "Epoch 22\n",
      "Epoch 23\n",
      "Epoch 24\n",
      "Epoch 25\n",
      "Epoch 26\n",
      "Epoch 27\n",
      "Epoch 28\n",
      "Epoch 29\n",
      "Iteration No: 9 ended. Evaluation done at random point.\n",
      "Time taken: 91.5424\n",
      "Function value obtained: -0.5884\n",
      "Current minimum: -0.6203\n",
      "Iteration No: 10 started. Evaluating function at random point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Epoch 10\n",
      "Epoch 11\n",
      "Epoch 12\n",
      "Epoch 13\n",
      "Epoch 14\n",
      "Epoch 15\n",
      "Epoch 16\n",
      "Epoch 17\n",
      "Epoch 18\n",
      "Epoch 19\n",
      "Epoch 20\n",
      "Epoch 21\n",
      "Epoch 22\n",
      "Epoch 23\n",
      "Epoch 24\n",
      "Epoch 25\n",
      "Epoch 26\n",
      "Epoch 27\n",
      "Epoch 28\n",
      "Epoch 29\n",
      "Epoch 30\n",
      "Epoch 31\n",
      "Epoch 32\n",
      "Epoch 33\n",
      "Epoch 34\n",
      "Epoch 35\n",
      "Epoch 36\n",
      "Epoch 37\n",
      "Epoch 38\n",
      "Epoch 39\n",
      "Iteration No: 10 ended. Evaluation done at random point.\n",
      "Time taken: 52.5789\n",
      "Function value obtained: -0.6101\n",
      "Current minimum: -0.6203\n",
      "Iteration No: 11 started. Searching for the next optimal point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Iteration No: 11 ended. Search finished for the next optimal point.\n",
      "Time taken: 26.5633\n",
      "Function value obtained: -0.5672\n",
      "Current minimum: -0.6203\n",
      "Iteration No: 12 started. Searching for the next optimal point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Iteration No: 12 ended. Search finished for the next optimal point.\n",
      "Time taken: 66.6966\n",
      "Function value obtained: -0.6202\n",
      "Current minimum: -0.6203\n",
      "Iteration No: 13 started. Searching for the next optimal point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Iteration No: 13 ended. Search finished for the next optimal point.\n",
      "Time taken: 59.4719\n",
      "Function value obtained: -0.6194\n",
      "Current minimum: -0.6203\n",
      "Iteration No: 14 started. Searching for the next optimal point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Iteration No: 14 ended. Search finished for the next optimal point.\n",
      "Time taken: 105.4072\n",
      "Function value obtained: -0.6184\n",
      "Current minimum: -0.6203\n",
      "Iteration No: 15 started. Searching for the next optimal point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Iteration No: 15 ended. Search finished for the next optimal point.\n",
      "Time taken: 113.1027\n",
      "Function value obtained: -0.6097\n",
      "Current minimum: -0.6203\n",
      "Iteration No: 16 started. Searching for the next optimal point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Iteration No: 16 ended. Search finished for the next optimal point.\n",
      "Time taken: 122.0533\n",
      "Function value obtained: -0.6185\n",
      "Current minimum: -0.6203\n",
      "Iteration No: 17 started. Searching for the next optimal point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Epoch 10\n",
      "Epoch 11\n",
      "Epoch 12\n",
      "Iteration No: 17 ended. Search finished for the next optimal point.\n",
      "Time taken: 138.7419\n",
      "Function value obtained: -0.6211\n",
      "Current minimum: -0.6211\n",
      "Iteration No: 18 started. Searching for the next optimal point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Iteration No: 18 ended. Search finished for the next optimal point.\n",
      "Time taken: 128.0581\n",
      "Function value obtained: -0.6188\n",
      "Current minimum: -0.6211\n",
      "Iteration No: 19 started. Searching for the next optimal point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Iteration No: 19 ended. Search finished for the next optimal point.\n",
      "Time taken: 132.0466\n",
      "Function value obtained: -0.6188\n",
      "Current minimum: -0.6211\n",
      "Iteration No: 20 started. Searching for the next optimal point.\n",
      "Epoch 0\n",
      "Epoch 1\n",
      "Epoch 2\n",
      "Epoch 3\n",
      "Epoch 4\n",
      "Epoch 5\n",
      "Epoch 6\n",
      "Epoch 7\n",
      "Epoch 8\n",
      "Epoch 9\n",
      "Epoch 10\n",
      "Iteration No: 20 ended. Search finished for the next optimal point.\n",
      "Time taken: 187.8376\n",
      "Function value obtained: -0.6131\n",
      "Current minimum: -0.6211\n",
      "Maximimum auc found: 0.62107\n",
      "Optimal parameters:\n",
      "epochs: 13\n",
      "learning_rate: 0.025599868607514464\n",
      "no_components: 107\n"
     ]
    }
   ],
   "source": [
    "space = [(1, 40), # epochs\n",
    "         (10**-4, 0.5, 'log-uniform'), # learning_rate\n",
    "         (20, 200), # no_components\n",
    "        ]\n",
    "\n",
    "res_fm = forest_minimize(objective, space, n_calls=20,\n",
    "                     random_state=0,\n",
    "                     verbose=True)\n",
    "print('Maximimum auc found: {:6.5f}'.format(-res_fm.fun))\n",
    "print('Optimal parameters:')\n",
    "params = ['epochs', 'learning_rate', 'no_components']\n",
    "for (p, x_) in zip(params, res_fm.x):\n",
    "    print('{}: {}'.format(p, x_))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def sample_recommendation_user(model, interactions, user_id, user_dict, \n",
    "                               item_dict,threshold = 0,nrec_items = 10, show = True):\n",
    "    '''\n",
    "    Function to produce user recommendations\n",
    "    Required Input - \n",
    "        - model = Trained matrix factorization model\n",
    "        - interactions = dataset used for training the model\n",
    "        - user_id = user ID for which we need to generate recommendation\n",
    "        - user_dict = Dictionary type input containing interaction_index as key and user_id as value\n",
    "        - item_dict = Dictionary type input containing item_id as key and item_name as value\n",
    "        - threshold = value above which the rating is favorable in new interaction matrix\n",
    "        - nrec_items = Number of output recommendation needed\n",
    "    Expected Output - \n",
    "        - Prints list of items the given user has already bought\n",
    "        - Prints list of N recommended items  which user hopefully will be interested in\n",
    "    '''\n",
    "    n_users, n_items = interactions.shape\n",
    "    user_x = user_dict[user_id]\n",
    "    scores = pd.Series(model.predict(user_x,np.arange(n_items)))\n",
    "    scores.index = interactions.columns\n",
    "    scores = list(pd.Series(scores.sort_values(ascending=False).index))\n",
    "    \n",
    "    known_items = list(pd.Series(interactions.loc[user_id,:][interactions.loc[user_id,:] > threshold].index) \\\n",
    "\t\t\t\t\t\t\t\t .sort_values(ascending=False))\n",
    "    \n",
    "    scores = [x for x in scores if x not in known_items]\n",
    "    return_score_list = scores[0:nrec_items]\n",
    "    known_items = list(pd.Series(known_items).apply(lambda x: item_dict[x]))\n",
    "    scores = list(pd.Series(return_score_list).apply(lambda x: item_dict[x]))\n",
    "    if show == True:\n",
    "        print(\"Known Likes:\")\n",
    "        counter = 1\n",
    "        for i in known_items:\n",
    "            print(str(counter) + '- ' + i)\n",
    "            counter+=1\n",
    "\n",
    "        print(\"\\n Recommended Items:\")\n",
    "        counter = 1\n",
    "        for i in scores:\n",
    "            print(str(counter) + '- ' + i)\n",
    "            counter+=1\n",
    "    return return_score_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def sample_recommendation_item(model,interactions,item_id,user_dict,item_dict,number_of_user):\n",
    "    '''\n",
    "    Funnction to produce a list of top N interested users for a given item\n",
    "    Required Input -\n",
    "        - model = Trained matrix factorization model\n",
    "        - interactions = dataset used for training the model\n",
    "        - item_id = item ID for which we need to generate recommended users\n",
    "        - user_dict =  Dictionary type input containing interaction_index as key and user_id as value\n",
    "        - item_dict = Dictionary type input containing item_id as key and item_name as value\n",
    "        - number_of_user = Number of users needed as an output\n",
    "    Expected Output -\n",
    "        - user_list = List of recommended users \n",
    "    '''\n",
    "    n_users, n_items = interactions.shape\n",
    "    x = np.array(interactions.columns)\n",
    "    scores = pd.Series(model.predict(np.arange(n_users), np.repeat(x.searchsorted(item_id),n_users)))\n",
    "    user_list = list(interactions.index[scores.sort_values(ascending=False).head(number_of_user).index])\n",
    "    return user_list \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.metrics.pairwise import cosine_similarity\n",
    "\n",
    "def create_item_emdedding_distance_matrix(model,interactions):\n",
    "    '''\n",
    "    Function to create item-item distance embedding matrix\n",
    "    Required Input -\n",
    "        - model = Trained matrix factorization model\n",
    "        - interactions = dataset used for training the model\n",
    "    Expected Output -\n",
    "        - item_emdedding_distance_matrix = Pandas dataframe containing cosine distance matrix b/w items\n",
    "    '''\n",
    "    df_item_norm_sparse = sparse.csr_matrix(model.item_embeddings)\n",
    "    similarities = cosine_similarity(df_item_norm_sparse)\n",
    "    item_emdedding_distance_matrix = pd.DataFrame(similarities)\n",
    "    item_emdedding_distance_matrix.columns = interactions.columns\n",
    "    item_emdedding_distance_matrix.index = interactions.columns\n",
    "    return item_emdedding_distance_matrix\n",
    "\n",
    "def item_item_recommendation(item_emdedding_distance_matrix, item_id, \n",
    "                             item_dict, n_items = 10, show = True):\n",
    "    '''\n",
    "    Function to create item-item recommendation\n",
    "    Required Input - \n",
    "        - item_emdedding_distance_matrix = Pandas dataframe containing cosine distance matrix b/w items\n",
    "        - item_id  = item ID for which we need to generate recommended items\n",
    "        - item_dict = Dictionary type input containing item_id as key and item_name as value\n",
    "        - n_items = Number of items needed as an output\n",
    "    Expected Output -\n",
    "        - recommended_items = List of recommended items\n",
    "    '''\n",
    "    recommended_items = list(pd.Series(item_emdedding_distance_matrix.loc[item_id,:]. \\\n",
    "                                  sort_values(ascending = False).head(n_items+1). \\\n",
    "                                  index[1:n_items+1]))\n",
    "    if show == True:\n",
    "        print(\"Item of interest :{0}\".format(item_dict[item_id]))\n",
    "        print(\"Item similar to the above item:\")\n",
    "        counter = 1\n",
    "        for i in recommended_items:\n",
    "            print(str(counter) + '- ' +  item_dict[i])\n",
    "            counter+=1\n",
    "    return recommended_items"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
